/*
 * Copyright(C) 2022. Huawei Technologies Co.,Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include <map>
#include <fstream>
#include "unistd.h"
#include <memory>
#include <queue>
#include <thread>
#include <boost/filesystem.hpp>
#include <opencv2/opencv.hpp>

#include "MxBase/DeviceManager/DeviceManager.h"
#include "MxBase/DvppWrapper/DvppWrapper.h"
#include "MxBase/MemoryHelper/MemoryHelper.h"

#include "MxBase/E2eInfer/ImageProcessor/ImageProcessor.h"
#include "MxBase/E2eInfer/VideoDecoder/VideoDecoder.h"
#include "MxBase/E2eInfer/VideoEncoder/VideoEncoder.h"
#include "MxBase/E2eInfer/DataType.h"

#include "MxBase/MxBase.h"
#include "MxBase/Log/Log.h"

#include <fairv2.h>
#include "cropResizePaste.hpp"

#include <MOTConnection.h>

#include <BlockingQueue.h>

using namespace MxBase;
namespace fs = boost::filesystem;

namespace
{
    const uint32_t SRC_WIDTH = 1280;
    const uint32_t SRC_HEIGHT = 720;
    const uint32_t RESIZE_WIDTH = 1088;
    const uint32_t RESIZE_HEIGHT = 608;
    const uint32_t MAX_WIDTH = 3840;
    const uint32_t MAX_HEIGHT = 2160;
    const uint32_t MAX_FRAME_COUNT = 5000;
    const uint32_t TARGET_FRAME_COUNT = 302;
    const uint32_t MS_TIMEOUT = 2000;
    const uint32_t DEVICE_ID = 0;
    const uint32_t CHANNEL_ID = 1;
    const std::string MODELPATH = "../models/mot_v2.om";
    const std::string TESTPATH = "../testimage/2.jpg";
}

APP_ERROR checkParams(const V2Param &v2Param)
{
    // check whether model file exists
    if (!fs::exists(v2Param.modelPath))
    {
        LogError << "Model file does not exist!Please check `modelPath`.";
        return APP_ERR_COMM_NO_EXIST;
    }
    return APP_ERR_OK;
}

int main(int argc, char *argv[])
{
    // global init
    APP_ERROR ret;
    ret = MxInit();
    if (ret != APP_ERR_OK)
    {
        LogError << "MxInit failed, ret=" << ret << ".";
        return ret;
    }
    // model init
    V2Param v2Param(DEVICE_ID, MODELPATH);
    ret = checkParams(v2Param);
    if (ret != APP_ERR_OK)
    {
        LogError << "Check params failed.Please read the log above for details.";
        return 0;
    }
    MxBase::Image decodedImage;
    auto tracker = std::make_shared<ascendVehicleTracking::MOTConnection>();
    auto fairModel = std::make_shared<FairMOT>(v2Param);
    ret = fairModel->ReadImage(TESTPATH, decodedImage);
    if (ret != APP_ERR_OK)
    {
        LogError << "ReadImage failed, ret=" << ret;
        return ret;
    }
    MxBase::Image resizeImage = resizeKeepAspectRatioFit(decodedImage.GetSize().width, decodedImage.GetSize().height,
                                                         RESIZE_WIDTH, RESIZE_HEIGHT, decodedImage, *fairModel->imageProcessorDptr);
    LogInfo << decodedImage.GetSize().width << decodedImage.GetSize().height;

    std::shared_ptr<MxBase::ImageProcessor> imageProcessorDptrone = std::make_shared<MxBase::ImageProcessor>(DEVICE_ID);
    imageProcessorDptrone->Encode(resizeImage, "../testimage/r2.jpg");
    // do infer
    std::vector<MxBase::Tensor> outputs;
    fairModel->Infer(resizeImage, outputs);
    // do the first postprocess
    std::vector<std::vector<MxBase::ObjectInfo>> objectInfos;
    ret = fairModel->PostProcessone(outputs, objectInfos);
    if (ret != APP_ERR_OK)
    {
        LogError << "videoDecoder Decode failed. ret is: " << ret;
    }
    return 0;
}
